/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.debugger.support; import java.beans.*; import java.util.*; import javax.swing.SwingUtilities; import org.openide.text.Line; import org.openide.debugger.DebuggerException; import org.netbeans.modules.debugger.support.util.Utils; public abstract class AbstractThread { // variables ....................................................................... protected AbstractDebugger debugger; private boolean current = false; private PropertyChangeSupport pcs; /** Points to parent thread group or contains null. */ private AbstractThreadGroup parentThreadGroup; // init ............................................................................ protected AbstractThread (AbstractDebugger debugger, AbstractThreadGroup parentThreadGroup) { this.parentThreadGroup = parentThreadGroup; this.debugger = debugger; pcs = new PropertyChangeSupport (this); } // main methods .................................................................... /** * Getter for the name of thread property. * * @throw DebuggerException if some problem occurs. * @return name of thread. */ public abstract String getName () throws DebuggerException; /** * Returns parent thread group. * * @return parent thread group. */ public AbstractThreadGroup getParentThreadGroup () { return parentThreadGroup; } /** * If this thread is suspended returns line number where this thread is stopped. * * @throw DebuggerException if some problem occurs. * @return line number where this thread is stopped. */ public abstract int getLineNumber () throws DebuggerException; /** * Returns string representation of the current state of this thread (depends on * debugger implementation). * * @throw DebuggerException if some problem occurs. * @return string representation of the current state of this thread. */ public abstract String getState () throws DebuggerException; /** * If this thread is suspended returns class name where this thread is stopped. * * @throw DebuggerException if some problem occurs. * @return class name where this thread is stopped. */ public abstract String getClassName () throws DebuggerException; /** * If this thread is suspended returns method name where this thread is stopped. * * @throw DebuggerException if some problem occurs. * @return method name where this thread is stopped. */ public abstract String getMethod () throws DebuggerException; /** * Returns current stack depth. * * @throw DebuggerException if some problem occurs. * @return current stack depth. */ public abstract int getStackDepth () throws DebuggerException; /** * Returns true if this thread is suspended. * * @throw DebuggerException if some problem occurs. * @return true if this thread is suspended. */ public abstract boolean isSuspended () throws DebuggerException; /** * Setter method for the suspend property. * * @throw DebuggerException if some problem occurs. * @param suspend true if this thread might be suspend. */ public void setSuspended (final boolean suspend) throws DebuggerException { //S ystem.out.println ("AbstractThread.setSuspended "+ suspend + " : " + isCurrent ()); // NOI18N if (isCurrent ()) { //S ystem.out.println ("AbstractThread.setSuspended "+ debugger); // NOI18N if (suspend) { setCurrent (true); debugger.updateWatches (); debugger.setDebuggerState (debugger.DEBUGGER_STOPPED); } else { debugger.unmarkCurrent (); debugger.setDebuggerState (debugger.DEBUGGER_RUNNING); } } SwingUtilities.invokeLater (new Runnable () { public void run () { firePropertyChange (null, null, null); } }); } /** * Returns true if this thread is current. */ public boolean isCurrent () { return current; } /** * Sets this thread current thread. * Calls debugger.setCurrentThread (this) and * marks current line in editor or show cursor on some stack frame * above, if current class is sourceless. * * @return true if the current thread switching is successfull. */ public boolean setCurrent (boolean current) { this.current = current; AbstractThread tt = debugger.getCurrentThread (); if (!current) { // set non-current if ( (tt != null) && tt.equals (this) ) debugger.setCurrentThread (null); if (getParentThreadGroup () != null) getParentThreadGroup ().setCurrent (false); SwingUtilities.invokeLater (new Runnable () { public void run () { pcs.firePropertyChange (null, null, null); } }); debugger.unmarkCurrent (); return true; } // make old current thread non-current if ((tt != null) && (tt != this)) tt.setCurrent (false); // change thread state (icon..) debugger.setCurrentThread (this); if (getParentThreadGroup () != null) getParentThreadGroup ().setCurrent (true); SwingUtilities.invokeLater (new Runnable () { public void run () { pcs.firePropertyChange (null, null, null); } }); if (debugger.isFollowedByEditor ()) { // mark current line in editor debugger.unmarkCurrent (); try { int ln = getLineNumber (); if (ln >=0) { Line l = getLine (); if (l != null) { debugger.markCurrent (l); return true; } } } catch (DebuggerException e) { } // set cursor otherwise CallStackFrame[] stack = getCallStack (); int i, k = stack.length; for (i = 1; i < k; i++) { try { if ( Utils.showInEditor ( stack [i].getLine () ) != null ) return true; } catch (DebuggerException ee) { } } } return true; } /** * Stops this thread. * * @throw DebuggerException if some problem occurs. */ public abstract void stop () throws DebuggerException; /** * If this thread is suspended returns line object representing position * in the editor where this thread is stopped. If thread has no stack returns null. * * @throws DebuggerException if informations about source are not included or some other error * occurres. * @return line object representing position where this thread is stopped. */ public org.openide.text.Line getLine () throws DebuggerException { try { String sn = getSourceName (); if (sn == null) return null; return Utils.getLineForSource ( getClassName (), getSourceName (), getLineNumber () ); } catch (DebuggerException e) { Line l = Utils.getLine ( getClassName (), getLineNumber () ); if (l != null) return l; throw e; } } /** * If this thread is suspended returns current call stack. * * @return current call stack. */ public abstract CallStackFrame[] getCallStack (); /** * If this thread is suspended returns current local variables. * * @return current local variables. */ public abstract AbstractVariable[] getLocales (); /** * Returns name of file of this frame or null if thread has no frame. * * @return Returns name of file of this frame. * @throws DebuggerException if informations about source are not included or some other error * occurres. */ public abstract String getSourceName () throws DebuggerException; /** * Adds property change listener for this thread. All property changes are fired * together in one PropertyChangeEvent with name of property == null. * * @param l listener to be added. */ public void addPropertyChangeListener (PropertyChangeListener l) { pcs.addPropertyChangeListener (l); } /** * Removes property change listener from this thread. * * @param l listener to be removed. */ public void removePropertyChangeListener (PropertyChangeListener l) { pcs.removePropertyChangeListener (l); } protected void firePropertyChange (String s, Object o, Object n) { pcs.firePropertyChange (s, o, n); } public String toString () { try { return "The Thread: " + getName () + " (" + super.toString () + ")"; // NOI18N } catch (Exception e) { return super.toString (); } } } /* * Log * 4 Gandalf-post-FCS1.2.3.0 3/28/00 Daniel Prusa * 3 Gandalf 1.2 1/14/00 Daniel Prusa NOI18N * 2 Gandalf 1.1 1/13/00 Daniel Prusa NOI18N * 1 Gandalf 1.0 11/8/99 Jan Jancura * $ */